/**
 * 客户端测试真实数据脚本
 * 专注于测试：直接使用token连接WebSocket、选择角色、查询背包信息
 */

const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');

const idList = [];
let dataList = [];
let dataObj = {};
let dataObj2 = {};

// 测试配置
const CONFIG = {
    server: {
        host: 'localhost',
        port: 3000,
        protocol: 'ws'
    },

    // 直接使用token连接
    // 请将下面的token替换为你的实际token
    // 可以通过以下方式获取token：
    // 1. 运行 test-code-1451.js 获取登录后的token
    // 2. 或者手动设置一个有效的token
    token: '79dc0fb7b1ea3f070ab1bf3fe3f5adc6', // 替换为你的实际token

    // 测试角色信息
    testCharacter: {
        name: '测试角色',
        sex: 1, // 1:男, 0:女
        roleType: 1, // 1:武士, 2:文人, 3:异师
        headIndex: 2
    }
};

class RealDataClientTestSimulator {
    constructor() {
        this.ws = null;
        this.characters = [];
        this.selectedCharacter = null;
        this.testResults = [];
        this.inventoryData = null;
        this.currentRequest = null; // { id, resolve, reject, timeout }
        this.results1297 = {}; // { [id]: { id, data } }
    }

    // 运行完整测试流程
    async runRealDataTest() {
        console.log('🚀 开始客户端背包功能测试...\n');
        console.log('测试目标：直接使用token连接WebSocket → 选择角色 → 查询背包信息\n');

        try {
            // 1. 直接建立WebSocket连接
            await this.testWebSocketConnection();

            // 打印测试结果
            this.printTestResults();

        } catch (error) {
            console.error('❌ 测试过程中发生错误:', error.message);
        }
    }

    timer = null;
    tempId = 1;

    start1267 = () => {
        // 已废弃: 此方法原用于 1267/713 调试，不再自动调用
    }

    // 发送 1297 指令并等待对应响应
    send1297AndWait(id, timeoutMs = 8000) {
        return new Promise((resolve, reject) => {
            try {
                // 防止并发：若上一个请求未结束，则拒绝（按设计我们串行调用，不应触发）
                if (this.currentRequest) {
                    return reject(new Error('上一个请求尚未完成'));
                }

                const payload = { c: 1297, d: { id } };
                this.ws.send(JSON.stringify(payload));

                const timeout = setTimeout(() => {
                    const err = new Error(`等待 1297 响应超时, id=${id}`);
                    if (this.currentRequest && this.currentRequest.reject) {
                        this.currentRequest.reject(err);
                    }
                    this.currentRequest = null;
                }, timeoutMs);

                this.currentRequest = { id, resolve, reject, timeout };
            } catch (err) {
                reject(err);
            }
        });
    }

    // 串行循环请求 1297: id 1-200，成功即写入文件，失败跳过
    async loop1297Sequential() {
        console.log('➡️ 开始串行请求 1297，范围 id=1..200');
        for (let id = 1; id <= 200; id++) {
            try {
                const resp = await this.send1297AndWait(id);
                if (resp && resp.code === 0) {
                    const entry = { id, data: resp.data };
                    this.results1297[id] = entry;
                    this.writeJsonToFile(this.results1297, 'zb_0911.json');
                } else {
                    // code 非 0 跳过
                }
            } catch (e) {
                // 超时或错误：跳过
            }
            // 略微间隔，避免请求过于密集
            await this.delay(50);
        }
        console.log('✅ 1297 串行请求完成');
    }



    // 1. WebSocket连接测试
    async testWebSocketConnection() {

        let _this = this;
        console.log('🔌 步骤1: WebSocket连接测试...');

        return new Promise((resolve, reject) => {
            try {
                const wsUrl = `ws://cd521.xin:8206/user-service/websocket?t=` + CONFIG.token;
                this.ws = new WebSocket(wsUrl);

                this.ws.on('open', async () => {
                    console.log('✅ WebSocket连接成功');

                    // 发送的数据: { "c": 1201, "d": { "id": 1583 } }
                    // WebSocketService.js:1 接收到数据:{"act_id":1201,"code":0,"data":{"ap":"165-195","czl":"0.96-1.1","descr":"吕布生前亲自带领的一支骑兵部队，战斗力非常强，吕布战败后投降曹操。","hp":"100-120","mp":"0-0","name":"燕云狼骑","s":4,"sp":"100-120"}}
                    //保持连接 禁止删除
                    this.ws.send(JSON.stringify({ c: 3 }));
                    //保持ws连接 禁止删除
                    this.ws.send(JSON.stringify({ "c": 5, "d": { "roleId": 2304 } }));
                    //保持ws连接 禁止删除
                    this.ws.send(JSON.stringify({ c: 100 }));
                    //保持ws连接 禁止删除
                    setInterval(() => {
                        this.ws.send(JSON.stringify({ c: 100 }));
                    }, 20000);
                    // this.ws.send(JSON.stringify({ c: 5280, d: { pageNum: 0 } }));
                    // new Array(100).fill(0).forEach(async (item, index) => {
                    //     const id = '' + index + 1;


                    //     // {"act_id":100,"area_id":100,"id":289,"imgType":16,"name":"许昌","num":6,"ss":5023,"type_id":6}
                    //     // {"c":1437,"d":{"siteId":289}}
                    // })
                    // 开始串行 1297 采集
                    this.loop1297Sequential().then(() => {
                        // 可按需在结束后关闭连接
                        // if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.close();
                        resolve();
                    }).catch(() => {
                        resolve();
                    });

                    // 等待一段时间确保数据接收完成，然后保存文件
                    // setTimeout(async () => {
                    //     console.log('\n📊 数据收集完成，开始保存文件...');
                    //     console.log(`📈 总共收集到 ${dataList.length} 条数据`);

                    //     // 保存数据到文件

                    //     // 关闭WebSocket连接
                    //     if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                    //         this.ws.close();
                    //     }

                    //     resolve();
                    // }, 13000); // 等待3秒确保数据接收完成
                });

                this.ws.on('error', (error) => {
                    console.log('❌ WebSocket连接失败:', error.message);
                    reject(error);
                });

                this.ws.on('close', () => {
                    console.log('🔌 WebSocket连接已关闭');
                });


                this.ws.on('message', (data) => {
                    try {
                        const message = JSON.parse(data);
                        // console.log('message', message.act_id);
                        if (message.act_id !== 3) {
                            // console.log('📨 收到消息:', JSON.stringify(message, null, 2));
                        }
                        // 仅处理 1297 的串行等待
                        if (message.act_id == 1297 && this.currentRequest) {
                            clearTimeout(this.currentRequest.timeout);
                            const { resolve } = this.currentRequest;
                            this.currentRequest = null;
                            resolve(message);
                        }
                        // {"act_id":1267,"code":0,"data":[{"k":"名称:","v":"跌打药"},{"k":"价格:","v":"50两"},{"k":"等级:","v":"1"},{"k":"负重:","v":"1"},{"k":"介绍:","v":"散瘀消肿，强筋健骨，可迅速补充气血。"}]}
                        // if (message.act_id == 1267) {
                        //     dataList.push({
                        //         [message.act_id]: message.data,
                        //     });
                        // }
                        // console.log('dataList.length', dataList.length);

                    } catch (error) {
                        _this.saveCurrentObjData();
                        console.log('文件已保存_this.tempId', _this.tempId);
                        console.error('❌ 消息解析失败:', data);
                    }
                });

            } catch (error) {
                reject(error);
            }
        });
    }

    // 将JSON对象保存为JSON文件
    writeJsonToFile(data, filename, outputDir = './output') {
        try {
            // 确保输出目录存在
            if (!fs.existsSync(outputDir)) {
                fs.mkdirSync(outputDir, { recursive: true });
                console.log(`📁 创建输出目录: ${outputDir}`);
            }

            // 生成完整的文件路径
            const filePath = path.join(outputDir, filename);

            // 将数据转换为格式化的JSON字符串
            const jsonString = JSON.stringify(data, null, 2);

            // 写入文件
            fs.writeFileSync(filePath, jsonString, 'utf8');

            console.log(`💾 数据已保存到文件: ${filePath}`);
            console.log(`📊 数据条数: ${Array.isArray(data) ? data.length : 'N/A'}`);

            return {
                success: true,
                filePath: filePath,
                message: '文件保存成功'
            };

        } catch (error) {
            console.error('❌ 保存文件失败:', error.message);
            return {
                success: false,
                error: error.message,
                message: '文件保存失败'
            };
        }
    }

    // 保存当前收集的数据到文件
    saveCurrentObjData() {

        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        const filename = `websocket_data_200_npcInfo.json`;
        const filename2 = `websocket_data_200_npcInfo.json`;

        const result = this.writeJsonToFile(dataObj2, filename);
        // const result2 = this.writeJsonToFile(dataObj2, filename2);

        if (result.success) {
            this.testResults.push({
                test: '数据保存测试',
                success: true,
                message: `成功保存 ${Object.keys(dataObj).length} 条数据到 ${result.filePath}`,
                timestamp: new Date().toLocaleString()
            });
        } else {
            this.testResults.push({
                test: '数据保存测试',
                success: false,
                message: `保存失败: ${result.message}`,
                timestamp: new Date().toLocaleString()
            });
        }
    }

    // 保存当前收集的数据到文件
    saveCurrentData() {
        if (dataList.length === 0) {
            console.log('⚠️  没有数据可保存');
            return;
        }

        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        const filename = `websocket_data_基础物品.json`;

        const result = this.writeJsonToFile(dataList, filename);

        if (result.success) {
            this.testResults.push({
                test: '数据保存测试',
                success: true,
                message: `成功保存 ${dataList.length} 条数据到 ${result.filePath}`,
                timestamp: new Date().toLocaleString()
            });
        } else {
            this.testResults.push({
                test: '数据保存测试',
                success: false,
                message: `保存失败: ${result.message}`,
                timestamp: new Date().toLocaleString()
            });
        }
    }

    // 延迟工具方法
    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // 深度比较两个复杂数组是否相同
    deepCompareArrays(arr1, arr2, options = {}) {
        const {
            ignoreOrder = false,        // 是否忽略数组元素顺序
            ignoreCase = false,         // 是否忽略字符串大小写
            ignoreNullUndefined = false, // 是否忽略null和undefined的差异
            maxDepth = 10,              // 最大递归深度，防止循环引用
            showDifferences = false     // 是否显示具体差异
        } = options;

        // 防止循环引用
        const visited = new WeakSet();

        const compare = (val1, val2, depth = 0) => {
            // 检查递归深度
            if (depth > maxDepth) {
                return { equal: false, reason: '递归深度超过限制，可能存在循环引用' };
            }

            // 基本类型比较
            if (val1 === val2) {
                return { equal: true };
            }

            // 处理null和undefined
            if (ignoreNullUndefined) {
                if ((val1 === null || val1 === undefined) &&
                    (val2 === null || val2 === undefined)) {
                    return { equal: true };
                }
            }

            // 类型检查
            if (typeof val1 !== typeof val2) {
                return { equal: false, reason: `类型不同: ${typeof val1} vs ${typeof val2}` };
            }

            // 处理null和undefined
            if (val1 === null || val1 === undefined ||
                val2 === null || val2 === undefined) {
                return { equal: false, reason: `空值不匹配: ${val1} vs ${val2}` };
            }

            // 处理日期对象
            if (val1 instanceof Date && val2 instanceof Date) {
                return { equal: val1.getTime() === val2.getTime() };
            }

            // 处理正则表达式
            if (val1 instanceof RegExp && val2 instanceof RegExp) {
                return { equal: val1.toString() === val2.toString() };
            }

            // 处理数组
            if (Array.isArray(val1) && Array.isArray(val2)) {
                if (val1.length !== val2.length) {
                    return { equal: false, reason: `数组长度不同: ${val1.length} vs ${val2.length}` };
                }

                if (ignoreOrder) {
                    // 忽略顺序的比较
                    const sorted1 = [...val1].sort((a, b) => {
                        if (typeof a === 'string' && typeof b === 'string') {
                            return ignoreCase ? a.toLowerCase().localeCompare(b.toLowerCase()) : a.localeCompare(b);
                        }
                        return String(a).localeCompare(String(b));
                    });
                    const sorted2 = [...val2].sort((a, b) => {
                        if (typeof a === 'string' && typeof b === 'string') {
                            return ignoreCase ? a.toLowerCase().localeCompare(b.toLowerCase()) : a.localeCompare(b);
                        }
                        return String(a).localeCompare(String(b));
                    });

                    for (let i = 0; i < sorted1.length; i++) {
                        const result = compare(sorted1[i], sorted2[i], depth + 1);
                        if (!result.equal) {
                            return { equal: false, reason: `数组元素不匹配(忽略顺序): ${result.reason}` };
                        }
                    }
                    return { equal: true };
                } else {
                    // 保持顺序的比较
                    for (let i = 0; i < val1.length; i++) {
                        const result = compare(val1[i], val2[i], depth + 1);
                        if (!result.equal) {
                            return { equal: false, reason: `数组元素不匹配(位置${i}): ${result.reason}` };
                        }
                    }
                    return { equal: true };
                }
            }

            // 处理对象
            if (typeof val1 === 'object' && typeof val2 === 'object') {
                // 检查循环引用
                if (visited.has(val1) || visited.has(val2)) {
                    return { equal: false, reason: '检测到循环引用' };
                }
                visited.add(val1);
                visited.add(val2);

                const keys1 = Object.keys(val1);
                const keys2 = Object.keys(val2);

                if (keys1.length !== keys2.length) {
                    return { equal: false, reason: `对象属性数量不同: ${keys1.length} vs ${keys2.length}` };
                }

                for (const key of keys1) {
                    if (!keys2.includes(key)) {
                        return { equal: false, reason: `对象缺少属性: ${key}` };
                    }

                    const result = compare(val1[key], val2[key], depth + 1);
                    if (!result.equal) {
                        return { equal: false, reason: `属性 ${key} 不匹配: ${result.reason}` };
                    }
                }

                return { equal: true };
            }

            // 处理字符串（考虑大小写忽略）
            if (typeof val1 === 'string' && typeof val2 === 'string') {
                if (ignoreCase) {
                    return { equal: val1.toLowerCase() === val2.toLowerCase() };
                }
                return { equal: val1 === val2 };
            }

            // 其他类型
            return { equal: val1 === val2 };
        };

        const result = compare(arr1, arr2);

        if (showDifferences && !result.equal) {
            console.log('🔍 数组比较差异详情:');
            console.log('数组1:', JSON.stringify(arr1, null, 2));
            console.log('数组2:', JSON.stringify(arr2, null, 2));
        }

        return result;
    }

    // 快速比较两个数组是否相同（简化版本）
    quickCompareArrays(arr1, arr2) {
        try {
            return JSON.stringify(arr1) === JSON.stringify(arr2);
        } catch (error) {
            return false;
        }
    }

    // 比较两个数组并返回差异报告
    compareArraysWithReport(arr1, arr2, options = {}) {
        const result = this.deepCompareArrays(arr1, arr2, options);

        if (result.equal) {
            return {
                equal: true,
                message: '✅ 两个数组完全相同',
                differences: []
            };
        }

        // 生成差异报告
        const differences = this.generateDifferencesReport(arr1, arr2, options);

        return {
            equal: false,
            message: '❌ 两个数组存在差异',
            reason: result.reason,
            differences: differences
        };
    }

    // 生成差异报告
    generateDifferencesReport(arr1, arr2, options = {}) {
        const differences = [];

        try {
            // 这里可以实现更详细的差异分析
            // 为了简化，我们返回基本的差异信息
            differences.push({
                type: 'basic',
                message: '使用 deepCompareArrays 方法获取详细差异信息',
                suggestion: '设置 showDifferences: true 查看完整数据'
            });
        } catch (error) {
            differences.push({
                type: 'error',
                message: '生成差异报告时出错',
                error: error.message
            });
        }

        return differences;
    }


    // 打印测试结果
    printTestResults() {
        console.log('\n' + '='.repeat(60));
        console.log('📊 客户端背包功能测试结果汇总');
        console.log('='.repeat(60));

        let passed = 0;
        let failed = 0;

        this.testResults.forEach((result, index) => {
            const status = result.success ? '✅' : '❌';
            const color = result.success ? '\x1b[32m' : '\x1b[31m';
            const reset = '\x1b[0m';

            console.log(`\n${status} 测试${index + 1}: ${result.test}`);
            console.log(`   结果: ${color}${result.success ? '通过' : '失败'}${reset}`);
            console.log(`   详情: ${result.message}`);
            console.log(`   时间: ${result.timestamp}`);

            if (result.success) passed++;
            else failed++;
        });

        console.log('\n' + '='.repeat(60));
        console.log(`📈 测试统计:`);
        console.log(`   总计: ${this.testResults.length} 个测试`);
        console.log(`   通过: ${passed} 个`);
        console.log(`   失败: ${failed} 个`);
        console.log(`   成功率: ${((passed / this.testResults.length) * 100).toFixed(1)}%`);

        if (failed === 0) {
            console.log('\n🎉 所有测试通过！背包功能测试成功！');
        } else {
            console.log('\n⚠️  部分测试失败，请检查相关功能。');
        }

        console.log('='.repeat(60));
        console.log('\n💡 测试流程: 直接使用token连接WebSocket → 查询角色 → 创建角色(如需要) → 选择角色 → 查询背包 → 验证背包功能');
        console.log('   确保服务器正在运行并且数据库连接正常');
        console.log('   背包查询使用act_id: 320指令');
        console.log('   请确保CONFIG.token配置了有效的token值');
    }
}

// 运行测试
async function main() {
    console.log('🎯 客户端背包功能测试模式');
    console.log('   专注于测试：直接使用token连接WebSocket、选择角色、查询背包信息\n');

    const simulator = new RealDataClientTestSimulator();
    await simulator.runRealDataTest();
}

// 如果直接运行此脚本
if (require.main === module) {
    main().catch((error) => {
        console.error('💥 测试脚本执行失败:', error.message);
        process.exit(1);
    });
}

module.exports = RealDataClientTestSimulator;